--
-- Incorporacion de stock secundario redundante en la tabla stk
--

ALTER TABLE public.stk
    ADD COLUMN stocksec numeric(16,2) NOT NULL DEFAULT 0;

ALTER TABLE public.stk
    ADD COLUMN stockminimosec numeric(16,2) NOT NULL DEFAULT 0;

ALTER TABLE public.stk
    ADD COLUMN reposicionsec  numeric(16,2) NOT NULL DEFAULT 0;

COMMENT ON COLUMN public.stk.stocksec
    IS 'Stock secundario para un deposito';

COMMENT ON COLUMN public.stk.stockminimosec
    IS 'Stock minimo por articulo-deposito para cantidad secundaria';

COMMENT ON COLUMN public.stk.reposicionsec
    IS 'Stock minimo por articulo-deposito para cantidad secundaria';

--
-- Esquema de stock por ubicación 
--

-- Table: stock.artubi

-- DROP TABLE stock.artubi;


CREATE SEQUENCE stock.seq_artubi
    INCREMENT 1
    START 1
    MINVALUE 1
    MAXVALUE 9223372036854775807
    CACHE 1;

ALTER SEQUENCE stock.seq_artubi
    OWNER TO abacouser;

CREATE TABLE IF NOT EXISTS stock.artubi
(
    id integer NOT NULL DEFAULT nextval('stock.seq_artubi'::regclass),
    codstkdep character varying(3) COLLATE pg_catalog."default" NOT NULL,
    cod character varying(20) COLLATE pg_catalog."default" NOT NULL,
    detalle character varying(50) COLLATE pg_catalog."default",
    pesopermitido numeric(10,2) DEFAULT 0.00,
    alto numeric(10,2) DEFAULT 0.00,
    largo numeric(10,2) DEFAULT 0.00,
    ancho numeric(10,2) DEFAULT 0.00,
    idambdb integer,
    fechainsert timestamp without time zone,
    fechaupdate timestamp without time zone,
    habilitada character varying(1) COLLATE pg_catalog."default" NOT NULL,
    CONSTRAINT artubi_pkey PRIMARY KEY (id),
    CONSTRAINT gestion_ai_artubistkdep FOREIGN KEY (codstkdep)
        REFERENCES public.stkdep (cod) MATCH SIMPLE
        ON UPDATE NO ACTION
        ON DELETE RESTRICT
)
WITH (
    OIDS = FALSE
)
TABLESPACE pg_default;

ALTER TABLE stock.artubi
    OWNER to abacouser;

COMMENT ON TABLE stock.artubi
    IS 'Ubicaciones fisicas de articulos';

COMMENT ON COLUMN stock.artubi.id
    IS 'Identificador del registro';

COMMENT ON COLUMN stock.artubi.codstkdep
    IS 'Codigo de deposito - redundante si el deposito esta en el codigo de la ubicacion';

COMMENT ON COLUMN stock.artubi.cod
    IS 'Codigo de ubicacion';

COMMENT ON COLUMN stock.artubi.detalle
    IS 'Descipción de la ubicacion';

COMMENT ON COLUMN stock.artubi.pesopermitido
    IS 'Peso permitido en la ubicacion - para relacionar con el peso de art';

COMMENT ON COLUMN stock.artubi.alto
    IS 'Alto disponible - para relacionar con el alto de art';

COMMENT ON COLUMN stock.artubi.largo
    IS 'Largo disponible - para relacionar con el largo de art';

COMMENT ON COLUMN stock.artubi.ancho
    IS 'Ancho permitido en la ubicacion - para relacionar con el ancho de art';

COMMENT ON COLUMN stock.artubi.idambdb
    IS 'Identificador de la instancia';

COMMENT ON COLUMN stock.artubi.fechainsert
    IS 'Fecha y hora de alta del registro';

COMMENT ON COLUMN stock.artubi.fechaupdate
    IS 'Fecha y hora ultima actualizacion del registro';

COMMENT ON COLUMN stock.artubi.habilitada
    IS 'Habilitacion de la ubicacion, una vez usadas no se deberian borrar por los movimientos historicos';
-- Index: artubi_unicidad

-- DROP INDEX stock.artubi_unicidad;

CREATE UNIQUE INDEX artubi_unicidad
    ON stock.artubi USING btree
    (cod COLLATE pg_catalog."default" ASC NULLS LAST)
    TABLESPACE pg_default;

-- Trigger: control_audit_artubi

-- DROP TRIGGER control_audit_artubi ON stock.artubi;

CREATE TRIGGER control_audit_artubi
    BEFORE INSERT OR DELETE OR UPDATE 
    ON stock.artubi
    FOR EACH ROW
    EXECUTE PROCEDURE public.tg_control_audit_instancia();

--
-- Ubicaciones sugeridas
--
CREATE SEQUENCE stock.seq_artubixart
    INCREMENT 1
    START 1
    MINVALUE 1
    MAXVALUE 9223372036854775807
    CACHE 1;

ALTER SEQUENCE stock.seq_artubixart
    OWNER TO abacouser;
    
    
CREATE TABLE IF NOT EXISTS stock.artubixart
(
    id integer NOT NULL DEFAULT nextval('stock.seq_artubixart'::regclass),
    idartubi integer NOT NULL,
    idart integer NOT NULL,
    stockminimo numeric(16,2) NOT NULL DEFAULT 0,
    reposicion numeric(16,2) NOT NULL DEFAULT 0,
    stockminimo_sec numeric(16,2) NOT NULL DEFAULT 0,
    reposicion_sec numeric(16,2) NOT NULL DEFAULT 0,
    idambdb integer,
    fechainsert timestamp without time zone,
    fechaupdate timestamp without time zone,
    CONSTRAINT artubixart_pkey PRIMARY KEY (id),
    CONSTRAINT gestion_ai_artubixartart FOREIGN KEY (idart)
        REFERENCES public.art (id) MATCH SIMPLE
        ON UPDATE NO ACTION
        ON DELETE CASCADE,
    CONSTRAINT gestion_ai_artubixartartubi FOREIGN KEY (idartubi)
        REFERENCES stock.artubi (id) MATCH SIMPLE
        ON UPDATE NO ACTION
        ON DELETE CASCADE
)
WITH (
    OIDS = TRUE
)
TABLESPACE pg_default;

ALTER TABLE stock.artubixart
    OWNER to abacouser;

COMMENT ON TABLE stock.artubixart
    IS 'Ubicaciones sugeridas por articulo - deposito';

COMMENT ON COLUMN stock.artubixart.idartubi
    IS 'Identificador de la ubicacion';

COMMENT ON COLUMN stock.artubixart.idart
    IS 'Identificador del articulo';

COMMENT ON COLUMN stock.artubixart.stockminimo
    IS 'Stock minimo en ubicacion';

COMMENT ON COLUMN stock.artubixart.reposicion
    IS 'Stock reposicion en ubicacion';

COMMENT ON COLUMN stock.artubixart.stockminimo_sec
    IS 'Stock secundario minimo en ubicacion';

COMMENT ON COLUMN stock.artubixart.reposicion_sec
    IS 'Stock secundario reposicion en ubicacion';

-- Trigger: control_audit_artubixart

-- DROP TRIGGER control_audit_artubixart ON stock.artubixart;

CREATE TRIGGER control_audit_artubixart
    BEFORE INSERT OR DELETE OR UPDATE 
    ON stock.artubixart
    FOR EACH ROW
    EXECUTE PROCEDURE public.tg_control_audit_instancia();


--
-- Funcion que genera ubicaciones con un algoritmo
-- Las ubicaciones se generan por extensión
--

-- FUNCTION: stock.poblarartubi(character varying, character varying, character varying, character varying, character varying, character varying, character varying, character varying, character varying, character varying, character varying, character varying, character varying, character varying, character varying)

-- DROP FUNCTION stock.poblarartubi(character varying, character varying, character varying, character varying, character varying, character varying, character varying, character varying, character varying, character varying, character varying, character varying, character varying, character varying, character varying);

CREATE OR REPLACE FUNCTION stock.poblarartubi(
	pcodstkdep character varying,
	pprefijo character varying,
	ppasilloinicial character varying,
	ppasillofinal character varying,
	plado character varying,
	palturainicial character varying,
	palturafinal character varying,
	pposicionincial character varying,
	pposicionfinal character varying,
	palto character varying,
	plargo character varying,
	pancho character varying,
	ppesomaximo character varying,
	pseparador character varying,
	pseparadores character varying)
    RETURNS integer
    LANGUAGE 'plpgsql'
    COST 100
    VOLATILE 
AS $BODY$
DECLARE

	vPasilloInicial integer;
	vPasilloFinal   integer;

	vAlturaInicial 	integer;
	vAlturaFinal	integer;
	vPosicionIncial integer;
	vPosicionFinal 	integer;
	vAlto			numeric(10,2);
	vlargo			numeric(10,2);
	vAncho			numeric(10,2);
	vPesoMaximo		numeric(10,2);
 	contador integer;
	
	
	
BEGIN
	BEGIN
		vPasilloInicial = CAST(pPasilloInicial 	as integer);
		vPasilloFinal   = CAST(pPasilloFinal 	as integer);
		vAlturaInicial 	= CAST(pAlturaInicial 	as integer);
		vAlturaFinal	= CAST(pAlturaFinal 	as integer);
		vPosicionIncial = CAST(pPosicionIncial 	as integer);
		vPosicionFinal 	= CAST(pPosicionFinal 	as integer);
		vAlto			= CAST(pAlto 		as numeric(10,2));
		vlargo			= CAST(plargo 		as numeric(10,2));
		vAncho			= CAST(pAncho 		as numeric(10,2));
		vPesoMaximo		= CAST(pPesoMaximo 	as numeric(10,2));
	EXCEPTION
		WHEN OTHERS THEN 
			 RAISE NOTICE 'Algun campo no tiene el valor correcto, verifique.';
	END;

	SELECT COUNT(*) into contador FROM stock.artubi;

	WITH cod_gen AS (
		SELECT
		    CAST(i AS varchar) as i, -- Genera 'cadena' a partir de pCodStkDep e i
			CAST(j AS varchar) as j,
			trim(to_char(ka, '00')) AS cadenitata -- Genera 'cadenitata' con ka
		FROM
			generate_series(vPasilloInicial, vPasilloFinal) AS i,  -- Serie de pasillos
			generate_series(vAlturaInicial, vAlturaFinal) AS j,    -- Serie de alturas
			generate_series(vPosicionIncial, vPosicionFinal) AS ka -- Serie de posiciones
	),
	lados AS (
		SELECT '0' AS lado
		WHERE pLado = '0' OR pLado = 'Ambos'
		UNION ALL
		SELECT '1' AS lado
		WHERE pLado = '1' OR pLado = 'Ambos'
	)

	INSERT INTO stock.artubi(codstkdep, cod, detalle, pesopermitido, alto, largo, ancho, habilitada)
	SELECT 
		pCodStkDep,
		pPrefijo ||
		case when substring(pSeparadores,1,1) = 'S' THEN pSeparador ELSE '' END ||
		i || -- Genera el código final con lado y cadenitata
		case when substring(pSeparadores,2,1) = 'S' THEN pSeparador ELSE '' END ||
		lado ||
		case when substring(pSeparadores,3,1) = 'S' THEN pSeparador ELSE '' END ||
		j ||
		case when substring(pSeparadores,4,1) = 'S' THEN pSeparador ELSE '' END ||
		cadenitata as cod,	
		'', -- Detalle (vacío)
		vPesoMaximo, -- Peso permitido
		vAlto, -- Alto
		vLargo, -- Largo
		vAncho, -- Ancho
		'S' -- Habilitada
	FROM cod_gen
	CROSS JOIN lados; 
	
	SELECT COUNT(*) - contador into contador FROM stock.artubi; 

	RETURN contador;
END;
$BODY$;

ALTER FUNCTION stock.poblarartubi(character varying, character varying, character varying, character varying, character varying, character varying, character varying, character varying, character varying, character varying, character varying, character varying, character varying, character varying, character varying)
    OWNER TO abacouser;

COMMENT ON FUNCTION stock.poblarartubi(character varying, character varying, character varying, character varying, character varying, character varying, character varying, character varying, character varying, character varying, character varying, character varying, character varying, character varying, character varying)
    IS 'Función para generar las cadenas que identifican una ubicacion, prefijo, pasillo, lado, altura y posicion con sus separadores, puede cambiar por cliente';

--
-- ATENCION: Se borran las viejas tablas relativas a Ubicaciones. Si se produce un error aquí habrá que ver que pasa.
-- 

   DROP TABLE public.artubixart;
   DROP TABLE public.artubi;
   
--
-- Nuevo campo idArtUbi en artm para indicar desde que lugar se saco/ingreso el stock por ubicacion
--

	
ALTER TABLE public.artm
    ADD COLUMN idartubi integer;

COMMENT ON COLUMN public.artm.idartubi
    IS 'Identificador de la ubicacion desde donde se movio el stock';

ALTER TABLE public.artm
    ADD CONSTRAINT gestion_ai_artubiartm FOREIGN KEY (idartubi)
    REFERENCES stock.artubi (id) MATCH SIMPLE
    ON UPDATE NO ACTION
    ON DELETE RESTRICT;
	

--
-- Vista de stock por ubicacion .. puede seguir así o convertirse en tabla si se pone espesa la performance
-- Si se convierte en tabla habrá que corregir los triggers (funciones en realidad) que actualizan STK para que también actualicen
-- 

CREATE OR REPLACE VIEW stock.vartubistk
 AS
 SELECT artm.idart,
    artm.idartubi,
    sum(artm.cant * artm.signo::numeric) AS stock,
    sum(artm.cantsec * artm.signo::numeric) AS stock_sec
   FROM artm
  WHERE artm.idartubi IS NOT NULL
  GROUP BY artm.idart, artm.idartubi;

ALTER TABLE stock.vartubistk
    OWNER TO abacouser;
    
    
--
-- Cambios en descxlike en lo que hace a las ubicaciones predeterminadas
--

CREATE OR REPLACE FUNCTION public.tg_art_ins_upd_descxlike()
    RETURNS trigger
    LANGUAGE 'plpgsql'
    COST 100
    VOLATILE NOT LEAKPROOF
AS $BODY$
-- ==============================
-- NOTA PARA EL IMPLEMENTADOR:
-- La funcion original queda en las (Trigger Functions) del esquema public con el nombre: tg_art_ins_upd_descxlike_bak();
-- POR CUESTIONES DE ORDEN, NUNCA se debe modificar esta funcion, sino la homonima del esquema cliente.
-- REGENERAR descxlike completo (toda la tabla): UPDATE art SET descxlike = descxlike;
-- ==============================
DECLARE
vDescXLike VARCHAR;
BEGIN
    vDescXLike :=
	NEW.Cod || ' ' || NEW.nombre || ' ' || 
	(SELECT nombre FROM artr WHERE (artr.tipoarta = NEW.tipoarta) AND (artr.cod = NEW.codartr)) || ' ' ||
	COALESCE(NEW.ubicacion, '') || ' ' || COALESCE(NEW.infobrowser, '') || ' ' ||
	(SELECT array_to_string(ARRAY(SELECT cod FROM artcodbar WHERE idart = NEW.id), ' ')) || ' ' ||
	(SELECT array_to_string(ARRAY(SELECT artubi.cod FROM stock.artubixart INNER JOIN stock.artubi ON artubixart.idartubi = artubi.id WHERE artubixart.idart = NEW.id), ' '));
    vDescXLike := cliente.tg_art_ins_upd_descxlike_ext(NEW.id, vDescXLike);
    vDescXLike := LOWER( SUBSTRING(vDescXLike, 1, 1000));
  -- postgresql evalua toda la condicion, da error el OLD si se usa en INSERT
   IF TG_OP = 'INSERT' THEN
        NEW.descxlike = vDescXLike;
   ELSIF vDescXLike <> COALESCE(OLD.descxlike, '') THEN
        NEW.descxlike = vDescXLike;
   END IF;
         
  RETURN NEW;
END;
$BODY$;

ALTER FUNCTION public.tg_art_ins_upd_descxlike()
    OWNER TO abacouser;
    
--
-- Modificacion de funciones de trigger de actualizacion de STK para incorporar el stock secundario
-- Primero debo modificar stock.actualizar_stk() agregando CantSec, que es la que los triggers llaman
-- El cambio en las funciones de trigger es agregar argumento CantSec en el llamado a stock.actualizar_stk(...).
--

/*

public.tg_artm_del_stk_y_ppp()
public.tg_artm_ins_stk_y_ppp()
public.tg_artm_upd_stk_y_ppp()

*/

--
-- Primero modifico la funcion que realmente actualiza STK 
-- Borro la funcion anterior porque cambia la cantidad de argumentos
--

DROP FUNCTION stock.actualizar_stk(integer, character varying, numeric);

--

CREATE OR REPLACE FUNCTION stock.actualizar_stk(pIdart integer, pCodStkDep varchar, pCant numeric, pCantSec numeric)
    RETURNS void
    LANGUAGE 'plpgsql'
    COST 100
    VOLATILE 
AS $BODY$
-- Actualiza la tabla de stock físico para un artículo dado en un depósito dado
BEGIN
	UPDATE public.Stk SET Stock = Stock + pCant, StockSec = StockSec + pCantSec 
	       WHERE (IdArt = pIdArt) AND (CodStkDep = pCodStkDep);
	IF (NOT FOUND) THEN
		INSERT INTO public.Stk (IdArt, CodStkDep, StockMinimo, Reposicion, Stock, StockSec,
							    idambdb, fechainsert, fechaupdate)
				VALUES (pIdArt, pCodStkDep, 0, 0, pCant, pCantSec, null, null, null);
	END IF;
	RETURN;
END;
$BODY$;

ALTER FUNCTION stock.actualizar_stk(integer, varchar, numeric, numeric)
    OWNER TO abacouser;

COMMENT ON FUNCTION stock.actualizar_stk(integer, varchar, numeric, numeric)
    IS 'Función para modificar el stk de un artículo en un depósito dado.';



-- DROP FUNCTION public.tg_artm_del_stk_y_ppp();

CREATE OR REPLACE FUNCTION public.tg_artm_del_stk_y_ppp()
    RETURNS trigger
    LANGUAGE 'plpgsql'
    COST 100
    VOLATILE NOT LEAKPROOF
AS $BODY$
-- Trigger de after delete sobre artm, si el artículo y el arco del artm eliminado registran y mueven stock,
-- respectivamente, se actualiza la tabla stk. Si el artículo es compuesto no se hace nada porque artmf
-- está en cascada y artmf mueve el stock
DECLARE
	vTipoCom ComM.TipoCom%TYPE;
	vRegistraStock Art.RegistraStock%TYPE;
	vStkComp Art.StkComp%TYPE;
BEGIN
-- Busca el comprobante padre del artm borrado (comm asociado)
SELECT TipoCom INTO vTipoCom FROM public.ComM WHERE (Id = OLD.IdComM);
-- Busca los valores de registra stock y si el artículo es compuesto
SELECT RegistraStock, StkComp INTO vRegistraStock, vStkComp FROM public.Art WHERE (Id = OLD.IdArt);
-- Llamo a actualizar precio promedio ponderado inmediatamente antes de actualizar el stock fisico.
IF vRegistraStock = 'S'  THEN
	PERFORM actualizar_ppp(OLD.IdArt, OLD.Cant * OLD.Signo * (-1), vTipoCom, OLD.ModificaStock, OLD.Precio, OLD.ImpoNogAux * OLD.Signo * (-1), OLD.CodStkDep, false);
END IF;
IF ((vRegistraStock = 'S') AND (OLD.ModificaStock = 'S')) THEN
	IF (vStkComp != 'C') THEN
-- Si el articulo registra stock, el arco modifica stock y el articulo no es compuesto, actualizo stk
		PERFORM stock.actualizar_stk(OLD.IdArt, OLD.CodStkDep, (-1) * OLD.Cant * OLD.Signo, (-1) * OLD.CantSec * OLD.Signo);
-- No hay else porque para articulos compuestos artmf está en cascada con artm
	END IF;
END IF;
RETURN NEW;
END;
$BODY$;

ALTER FUNCTION public.tg_artm_del_stk_y_ppp()
    OWNER TO abacouser;

COMMENT ON FUNCTION public.tg_artm_del_stk_y_ppp()
    IS 'Cuerpo del trigger de artm que actualiza el stock físico de los artículos al eliminar un movimiento de artículo. De paso actualiza precio promedio ponderado';


--
-- Insert
--

CREATE OR REPLACE FUNCTION public.tg_artm_ins_stk_y_ppp()
    RETURNS trigger
    LANGUAGE 'plpgsql'
    COST 100
    VOLATILE NOT LEAKPROOF
AS $BODY$
-- Trigger de after insert sobre artm, según si el articulo registra stock y el arco de stock mueve el
-- stock fisico, actualiza la tabla de stock o llamo a un procedimiento para expander un articulo
-- compuesto en artmf.
DECLARE
	vTipoCom ComM.TipoCom%TYPE;
	vRegistraStock Art.RegistraStock%TYPE;
	vStkComp Art.StkComp%TYPE;
BEGIN
-- Busca el comprobante padre del artm considerado (comm asociado)
	SELECT TipoCom INTO vTipoCom FROM public.ComM WHERE (Id = NEW.IdComM);
	-- Busca los valores de registra stock y si el articulo es compuesto
	SELECT RegistraStock, StkComp INTO vRegistraStock, vStkComp FROM public.Art WHERE (Id = NEW.IdArt);
	-- Llamo a actualizar precio promedio ponderado inmediatamente antes de actualizar el stock fisico.
	IF vRegistraStock = 'S'  THEN
		PERFORM actualizar_ppp(NEW.IdArt, NEW.Cant * NEW.Signo, vTipoCom, NEW.ModificaStock, NEW.Precio, NEW.ImpoNogAux * NEW.Signo, NEW.CodStkDep, false);
	END IF;
	IF ((vRegistraStock = 'S') AND (NEW.ModificaStock = 'S')) THEN
		IF (vStkComp = 'C') THEN
		-- Si el articulo registra stock, el arco modifica stock, pero el articulo es compuesto, se llama
		-- al procedimiento para esa actualizacion de stock de articulos compuestos.
			PERFORM stock.agregar_art_compuestos(NEW.IdArt, NEW.Cant * NEW.Signo, NEW.Id, NEW.CodStkDep);
		ELSE
		-- Si el articulo registra stock, el arco modifica stock y el articulo no es compuesto, actualizo stk
			PERFORM stock.actualizar_stk(NEW.IdArt, NEW.CodStkDep, NEW.Cant * NEW.Signo, NEW.CantSec * NEW.Signo);
		END IF;
	END IF;
	RETURN NEW;
END;
$BODY$;

ALTER FUNCTION public.tg_artm_ins_stk_y_ppp()
    OWNER TO abacouser;

COMMENT ON FUNCTION public.tg_artm_ins_stk_y_ppp()
    IS 'Cuerpo del trigger de artm que actualiza el stock físico de los artículos al agregar un movimiento de artículo. De paso actualiza precio promedio ponderado';


-- FUNCTION: public.tg_artm_upd_stk_y_ppp()

-- DROP FUNCTION public.tg_artm_upd_stk_y_ppp();

CREATE OR REPLACE FUNCTION public.tg_artm_upd_stk_y_ppp()
    RETURNS trigger
    LANGUAGE 'plpgsql'
    COST 100
    VOLATILE NOT LEAKPROOF
AS $BODY$
-- Trigger de after update sobre artm. Dependiendo de si el articulo viejo registra stock y el arco mueve stock,
-- elimina los artmf (los cuales actualizan stk) para articulos compuestos, o actualiza stk para el
-- articulo viejo y decrementa la cantidad en la cantidad vieja.
DECLARE
	vRegistraStock Art.RegistraStock%TYPE;
	vStkComp Art.StkComp%TYPE;
	vTipoCom ComM.TipoCom%TYPE;
	vDeboRecalcularPPP boolean;
	vDeboActualizarFisico boolean;
	vCorregirFisico_PPP boolean;
	vStockAnterior numeric(16,2);
BEGIN
	-- Busca el comprobante padre del artm considerado (comm asociado)
	SELECT TipoCom INTO vTipoCom FROM public.ComM WHERE (Id = OLD.IdComM);
	-- Busca los valores de registra stock y si el articulo es compuesto, para el articulo viejo
	SELECT RegistraStock, StkComp INTO vRegistraStock, vStkComp FROM public.Art WHERE Id = OLD.IdArt;
	-- Si cambia la cantidad, el arco de stock, el deposito o el articulo y el art
	vDeboActualizarFisico :=  ( (OLD.IdArt != NEW.IdArt) OR (OLD.Cant != NEW.Cant) OR (OLD.CantSec != NEW.CantSec) OR 
								(OLD.CodStkDep != NEW.CodStkDep) OR (OLD.OrigenCodStkEst != NEW.OrigenCodStkEst) OR (OLD.CodStkEst != NEW.CodStkEst)
							  ); 

	--  Si cambia la cantidad, el arco de stock, el deposito o el articulo, el precio o el ImpoNoGAux 
	vDeboRecalcularPPP :=  ( (OLD.IdArt != NEW.IdArt) OR (OLD.Cant != NEW.Cant) OR (OLD.CodStkDep != NEW.CodStkDep) OR
							(OLD.OrigenCodStkEst != NEW.OrigenCodStkEst) OR (OLD.CodStkEst != NEW.CodStkEst) OR
							(OLD.precio != NEW.precio) OR (OLD.imponogaux != NEW.imponogaux)
						   );
	-- OLD
	vCorregirFisico_PPP := False;  
	-- Llamo a actualizar precio promedio ponderado inmediatamente antes de actualizar el stock fisico.
	IF (vRegistraStock = 'S') AND vDeboRecalcularPPP THEN
		PERFORM actualizar_ppp(OLD.IdArt, OLD.Cant * OLD.Signo * (-1), vTipoCom, OLD.ModificaStock, OLD.Precio, OLD.ImpoNogAux * OLD.Signo * (-1), OLD.CodStkDep, vCorregirFisico_PPP);
	END IF;
	IF (vRegistraStock = 'S') AND (OLD.ModificaStock = 'S') AND vDeboActualizarFisico THEN
		IF (vStkComp = 'C') THEN
			-- Si es articulo compuesto elimino los artmf para luego volverlos a crear, en lugar de hacer updates
			DELETE FROM public.artmf WHERE (IdArtM = OLD.Id);
		ELSE
	-- Si el articulo registra stock, el arco modifica stock y el articulo no es compuesto, actualizo stk
			PERFORM stock.actualizar_stk(OLD.IdArt, OLD.CodStkDep, (-1) * OLD.Cant * OLD.Signo, (-1) * OLD.CantSec * OLD.Signo);
		END IF;
	END IF;
	-- NEW
	-- Si no se actualizo el stock fisico, hay que informarlo a la funcion actualizar_ppp
	vCorregirFisico_PPP := NOT ( (NEW.ModificaStock = 'S') AND vDeboActualizarFisico);
	-- Busca los valores de registra stock y si el articulo es compuesto, para el articulo nuevo
	SELECT RegistraStock, StkComp INTO vRegistraStock, vStkComp FROM public.Art WHERE Id = NEW.IdArt;
	-- Llamo a actualizar precio promedio ponderado inmediatamente antes de actualizar el stock fisico.
	IF (vRegistraStock = 'S') AND vDeboRecalcularPPP THEN
		PERFORM actualizar_ppp(NEW.IdArt, NEW.Cant * NEW.Signo, vTipoCom, NEW.ModificaStock, NEW.Precio, NEW.ImpoNogAux  * NEW.Signo, NEW.CodStkDep, vCorregirFisico_PPP);
	END IF;
	IF (vRegistraStock = 'S') AND (NEW.ModificaStock = 'S') AND vDeboActualizarFisico THEN
		IF (vStkComp = 'C') THEN
			-- Si el articulo registra stock, el arco modifica stock, pero el articulo es compuesto llamo
			-- un procedimiento para esa actualizacion de stock de articulos compuestos.
			PERFORM stock.agregar_art_compuestos(NEW.IdArt, NEW.Cant * NEW.Signo, NEW.Id, NEW.CodStkDep);
		ELSE
			-- Si el articulo registra stock, el arco modifica stock y el articulo no es compuesto, actualizo stk
			PERFORM stock.actualizar_stk(NEW.IdArt, NEW.CodStkDep, NEW.Cant * NEW.Signo, NEW.CantSec * NEW.Signo);
		END IF;
	END IF;
	RETURN NEW;
END;
$BODY$;

ALTER FUNCTION public.tg_artm_upd_stk_y_ppp()
    OWNER TO abacouser;

COMMENT ON FUNCTION public.tg_artm_upd_stk_y_ppp()
    IS 'Cuerpo del trigger de artm que actualiza el stock físico de los artículos al modificar un movimiento de artículo. De paso actualiza precio promedio ponderado';

--
-- Tambien se modifica la tabla de redundancia de stock pendiente : public.stkestxart para que maneje cantsec
--
-- Tambien se modifica la funcion de trigger de redundancia de stock pendientes, que 
-- llama a stock.actualizar_stkestxart(...) que tambien se modifica agregando CantSec.
-- Primero modifico stock.actualizar_stkestxart agregando cantsec
--

ALTER TABLE public.stkestxart
    ADD COLUMN cantsec numeric(16,2) default 0 NOT NULL;
	
COMMENT ON COLUMN public.stkestxart.cantsec
    IS 'Cantidad secundaria';

/*

public.tg_artm_ins_upd_del_stkestxart()

*/

DROP FUNCTION stock.actualizar_stkestxart(character varying, character varying, character varying, integer, numeric);

CREATE OR REPLACE FUNCTION stock.actualizar_stkestxart(pCodStkEst varchar, pCodStkDep varchar, pPresupuesto varchar, pIdArt integer, pCant numeric, pCantSec numeric)
    RETURNS void
    LANGUAGE 'plpgsql'
    COST 100
    VOLATILE
AS $BODY$
DECLARE
	-- Actualiza la tabla de stkestxart (stock pendiente por nodo, deposito y articulo)
BEGIN
	IF (pCodStkEst <> '<E>') AND (pCodStkEst <> '<X>') AND  (substring(pCodStkEst, 1, 1) <> '@')  AND  (coalesce(pPresupuesto, 'N') = 'N') THEN
		UPDATE public.stkestxart set cant = cant + pCant, cantsec = cantsec + pCantSec 
		WHERE codstkest = pCodStkEst and codstkdep = pCodStkDep and idart = pIdArt;
		IF (NOT FOUND) THEN
			INSERT INTO public.stkestxart(codstkest, codstkdep, idart, cant, cantsec)
			VALUES ( pCodStkEst, pCodStkDep, pIdArt, pCant, pCantSec );
		END IF;
		--    Borro la fila si lo pendiente es cero para dejar la tabla limpia.
		--  Con el agregado de cantsec esto se va a complicar Ric 9/2024
		IF EXISTS (select * from public.stkestxart 
				   where codstkest = pCodStkEst and codstkdep = pCodStkDep and idart = pIdArt and cant = 0.00 and cantsec = 0.00) THEN
			DELETE FROM public.stkestxart where codstkest = pCodStkEst and codstkdep = pCodStkDep and idart = pIdArt and cant = 0.00 and cantsec = 0.00;
		END IF;
	END IF;
	RETURN;
END;
$BODY$;

ALTER FUNCTION stock.actualizar_stkestxart(character varying, character varying, character varying, integer, numeric, numeric)
    OWNER TO abacouser;

COMMENT ON FUNCTION stock.actualizar_stkestxart(character varying, character varying, character varying, integer, numeric, numeric)
    IS 'Procedimiento que actualiza la tabla de stkestxart (stock pendiente por nodo, deposito y articulo)';

--
-- Funcion de Trigger
--

CREATE OR REPLACE FUNCTION public.tg_artm_ins_upd_del_stkestxart()
    RETURNS trigger
    LANGUAGE 'plpgsql'
    COST 100
    VOLATILE NOT LEAKPROOF
AS $BODY$
BEGIN
-- Actualizo el stock pendiente en la tabla stkestxart para los dos nodos en que puede incidir (artm.codstkest y artm.origencodstkest).
	IF (TG_OP = 'INSERT') THEN
		PERFORM stock.actualizar_stkestxart(NEW.codstkest, NEW.CodStkDep, NEW.Presupuesto, NEW.idart, NEW.cant, NEW.cantsec);
		PERFORM stock.actualizar_stkestxart(NEW.origencodstkest, NEW.CodStkDep, NEW.Presupuesto, NEW.idart, -1 * NEW.cant, -1 * NEW.cantsec);
	END IF;
	IF (TG_OP = 'DELETE') THEN
		PERFORM stock.actualizar_stkestxart(OLD.codstkest, OLD.CodStkDep, OLD.Presupuesto, OLD.idart, -1 * OLD.cant, -1 * OLD.cantsec);
		PERFORM stock.actualizar_stkestxart(OLD.origencodstkest, OLD.CodStkDep, OLD.Presupuesto, OLD.idart, OLD.cant, OLD.cantsec);
	END IF;
	IF (TG_OP = 'UPDATE')  THEN
		IF (OLD.idart <> NEW.idart or OLD.cant <> NEW.cant)  THEN
			PERFORM stock.actualizar_stkestxart(OLD.codstkest, OLD.CodStkDep, OLD.Presupuesto, OLD.idart, -1 * OLD.cant, -1 * OLD.cantsec);
			PERFORM stock.actualizar_stkestxart(OLD.origencodstkest, OLD.CodStkDep, OLD.Presupuesto, OLD.idart, OLD.cant, OLD.cantsec);
			PERFORM stock.actualizar_stkestxart(NEW.codstkest, NEW.CodStkDep, NEW.Presupuesto, NEW.idart, NEW.cant, NEW.cantsec);
			PERFORM stock.actualizar_stkestxart(NEW.origencodstkest, NEW.CodStkDep, NEW.Presupuesto, NEW.idart, -1 * NEW.cant, -1 * NEW.cantsec);
		END IF;
	END IF;
	RETURN NEW;
END;
$BODY$;

ALTER FUNCTION public.tg_artm_ins_upd_del_stkestxart()
    OWNER TO abacouser;

    
    
    
--
SELECT aaVersion('519.00','518.09');
--

